/*
 * Copyright 2009 Douglas Lockamy, dlockamy_at_gmail.com
 * All rights reserved. Distributed under the terms of the MIT License.
 */

if (!this.benix) benix = {};

debug=0;

benix.version = '0.1';

benix.user;
benix.password;
benix.currentDir = '/';
benix.rootPath;
benix.stdoutBuffer = '';

benix.stdoutReg;
benix.stdinReg;

benix.KeyUpReg;

benix.mouseMoveReg;
benix.mouseDownReg;
benix.mouseUpReg;

benix.onSelectReg;

benix.tickReg;
benix.browser;

/*
    File System interface:
    
    mount(serverAddress,fs_type,mountPoint);
    umount(mountPoint);
    read(path,flags,buffer);
    write(path,flags,buffer);
*/

benix.init = function()
{
    benix.browser();
    benix.ajaxObj = new benix.ajaxBuilder();

    benix.stdoutReg = new Array();
    benix.stdinReg = new Array(); 

    benix.KeyUpReg = new Array();
    
    benix.mouseMoveReg = new Array();
    benix.mouseDownReg = new Array();
    benix.mouseUpReg = new Array();
    
    benix.onSelectReg = new Array();
    
    benix.tickReg =  new Array();   

    vfs.init();
    benix.procInit();
    
    vfs.mount(null,'procfs','/local/proc',null,null,null); 
    
    document.onmousedown = benix.MouseDown;
    document.onmouseup = benix.MouseUp;
    document.onmousemove = benix.MouseMove;
    document.onkeydown = benix.stdin;
    document.onkeyup = benix.KeyUp;
    
    document.onselect = benix.OnSelect;
 
    vfs.mount(null,'wmfs','/local/window',null,null,null);

    vfs.write('/dev/window',4,'/local/window',null,null,null);
    vfs.write('/dev/window',4,'/remote/0/dev/window',null,null,null);
        
    benix.tick('start');

    benix.procLoop();
 
    benix.stdout('Start benix for ' + benix.browser + '<br>');    
    login.main();
};

benix.browser = function() 
{
    this.IE = false;
    this.Firefox = false;
    this.Safari = false;
    this.version = null;

    agent = navigator.userAgent;
    s = "MSIE";
    if ((i = agent.indexOf(s)) >= 0)
    {
        this.IE = true;
        //benix.browserVersion = parseFloat(agent.substr(i + s.length) );
        benix.browser='IE';
        alert('We\'re Sorry, IE is not capable of displaying this content. Consider Firefox or Safari for your browsing needs');
        return;
    }

    s = "WebKit";
    if ((i = agent.indexOf(s)) >= 0)
    {
        this.SAFARI = true;
        benix.browserVersion = parseFloat(agent.substr(i + s.length) );
        benix.browser='Safari';
        return;
    }
    s = "Firefox";
    if ((i = agent.indexOf(s)) >= 0)
    {
        this.FIREFOX = true;
        benix.browserVersion = parseFloat(agent.substr(i + s.length) );
        benix.browser='Firefox';
        return;
    }
    s = "Chrome";
    if ((i = agent.indexOf(s)) >= 0)
    {
        this.CHROME = true;
        benix.browserVersion = parseFloat(agent.substr(i + s.length) );
        benix.browser='Chrome';      
        return;
    }
};

benix.ajaxObj;

benix.ajaxBuilder = function()
{
//based on wikipedia's demo emplimentation
    try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch(e){
        try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch(e){
            try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e){
                try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e){
                    try { return new XMLHttpRequest() } catch(e){
                        throw new Error( "This browser does not support XMLHttpRequest." );
                    }
                }
            }
        }
    }
};

benix.wget = function(url)
{
    //if( 
    wget_ajaxObj = new benix.ajaxBuilder();
    wget_ajaxObj.open("GET",url,false);
    //{
        wget_ajaxObj.send(null);
        alert(wget_ajaxObj.responseText);
        return(wget_ajaxObj.responseText); 
    //}
    //else
        return -1;
};

benix.wput = function(url,file)
{
    //if( 
    benix.ajaxObj.open("PUT",url,false);
    //{
        benix.ajaxObj.send(null);
        return(benix.ajaxObj.responseText); 
    //}
    //else
        return -1;

    return 0;
};

benix.registerOnSelect = function( stdinObj )
{
    benix.onSelectReg[length] = stdinObj;
};

benix.registerMouseDown = function( stdinObj )
{
    benix.mouseDownReg[length] = stdinObj;
};

benix.registerMouseUp = function( stdinObj )
{
    benix.mouseUpReg[length] = stdinObj;
};

benix.registerMouseMove = function( stdinObj )
{
    benix.mouseMoveReg[length] = stdinObj;
};

benix.OnSelect = function(event)
{
    count = 0;

    while(count <= benix.onSelectReg.length-1)
    {
        benix.mouseUpReg[count].onSelect(event);
        count++;
    };
};

benix.MouseDown = function(event)
{
    count = 0;

    while(count <= benix.mouseDownReg.length-1)
    {
        benix.mouseUpReg[count].mouseDown(event);
        count++;
    };
};

benix.MouseUp = function(event)
{
    count = 0;

    while(count <= benix.mouseUpReg.length-1)
    {
        benix.mouseUpReg[count].mouseUp(event);
        count++;
    };
};

benix.MouseMove = function(event)
{
    count = 0;
    
    while(count <= benix.mouseMoveReg.length-1)
    {
        benix.mouseUpReg[count].mouseMove(event);
        count++;
    };
};  

benix.debug = function(formatedString)
{
    if(debug)
        benix.stdout(formatedString);
};

benix.stdout = function( formatedString )
{
    if(benix.stdoutBuffer.length < 80 )
    {
        benix.stdoutBuffer = benix.stdoutBuffer + formatedString;
        if(document.getElementById('content'))
            document.getElementById('content').innerHTML = benix.stdoutBuffer;
    }
    else
    {
        benix.stdoutBuffer = formatedString;
        if(document.getElementById('content'))
            document.getElementById('content').innerHTML = benix.stdoutBuffer;    
    }
};

keyCodeMapper= function(event)
{
    //alert(event.keyCode);
    
    //we should be mapping against an array of key codes and characters
    /*
    return(keyArray[event.keyCode] );
    */
        if(event.keyCode >= 48 && event.keyCode <= 57 )
    {
        currChar = String.fromCharCode(event.keyCode);
        
        if(event.shiftKey)
             bash.buffer += currChar;       
        else
            currChar = currChar.toLowerCase(); 
            //alert(currChar);    
    }
    
    else if(event.keyCode >= 65 && event.keyCode <=90 )
    {
        currChar = String.fromCharCode(event.keyCode);
        
        if(event.shiftKey)
             bash.buffer += currChar;       
        else
            currChar = currChar.toLowerCase();     
    }
    else if(event.keyCode >= 48 && event.keyCode <=55 )
        currChar = parseInt( String.fromCharCode(event.keyCode) );

    else if(event.keyCode >= 96 && event.keyCode <=105 )
        currChar = parseInt( String.fromCharCode(event.keyCode) );

    else if(event.keyCode==13)
    {   
        currChar = "\\n";  
    }

    else if(event.keyCode==191)
       currChar= '/'; 
 
    else if(event.keyCode==8)
        currChar = '\\bck';
 
    else if(event.keyCode == 186)
    {        
        //if(event.shiftKey)
            currChar = ':';       
        //else
         //   currChar = ';';   
    }  
    
    else if(event.keyCode == 191)
    {
        currChar = '/'; 
    }

    else if(event.keyCode == 190)
    {
        currChar = '.'; 
    }
 
    else if(event.keyCode == 32)
    {
        currChar = ' '; 
    }
     else if(event.keyCode == 16)
    {
        return;
    }
     else if(event.keyCode == 192)
    {
        currChar = '*';
    }
    
    return currChar;
};

benix.stdin = function(event)
{
    count = 0;

    if(event.keyCode == 16)
    {
        return;
    }
    else
        var currChar = keyCodeMapper(event);

    if(benix.username && benix.password)
    {
        while(count <= benix.stdinReg.length-1)
        {
            benix.stdinReg[count].keydown(currChar);
            count++;
        };
        
        wmfs.keyDown(event);
    }
    else
        login.input(currChar);
};

benix.registerStdin = function( stdinObj )
{
    benix.stdinReg[length ] = stdinObj;
};

benix.keyUp = function(event)
{
    count = 0;

    if(benix.username && benix.password)
    {
        while(count <= benix.KeyUpReg.length-1)
        {
            benix.KeyUpReg[count].keydown(event);
            count++;
        };        
        
        wmfs.keyUp(event);
    }
    else
        login.input(event);
};

benix.registerKeyUp = function( stdinObj )
{
    benix.KeyUpReg[length ] = stdinObj;
};

benix.flush = function(arg)
{
    if(arg == 'stdout')
    {
        benix.stdoutBuffer = "";
        content.innerHTML = benix.stdoutBuffer;
    }
}

benix.registerTick = function( arg )
{
    benix.tickReg[length ] = arg;
};

benix.tick = function(arg)
{
    count = 0;

    while(count <= benix.tickReg.length-1)
    {
        benix.tickReg[count].tick(arg);
        count++;
    };
    
    setTimeout(benix.tick,20);
    
};

benix.read = function(path,flags,buffer,offset,length,sessionKey)
{
    //if(!sessionKey)
      //  return -1;
    //else
        return(vfs.read(path,flags,buffer,offset,length,sessionKey) ); 
};

benix.write = function(path,flags,buffer,offset,length,sessionKey)
{
    //if(!sessionKey)
    //    return -1;
    //else
        return(vfs.write(path,flags,buffer,offset,length,sessionKey));
};

benix.procList=0;

benix.procInit = function()
{
    benix.procList = new Array();
};

benix.procExec = function(procClass,flags)
{
    benix.procList[benix.procList.length ] = procClass;
    procClass.init(flags);
};

benix.procLoop = function()
{
    count = 0;
    while(count < benix.procList.length)
    {
        benix.procList[count].isRunning=true;
        benix.procList[count].Run();
        benix.procList[count].isRunning=false;
        count++;
    };
    
    setTimeout(benix.procLoop,20);
};

benix.procEndTask = function(procClassName)
{

};

benix.fsMakeNode = function(rootNode,path)
{

};

benix.fsRemoveNode = function(rootNode,path)
{

};

benix.fsCopy = function(sourcePath,destPath,flags)
{
    benix.stdout("copy"+sourcePath+"to"+destPath+"<br>");
    if(sourcePath[sourcePath.length-1]=="*" && flags=="0r")
    {
        var cleanCount = 1;
        var cleanPath = "";
        var splitPath =  sourcePath.split("/"); 
        while(cleanCount < splitPath.length-1 )
        {
            cleanPath = cleanPath+"/"+splitPath[cleanCount];                
            cleanCount++;
        };
               
        readNode =  benix.read(cleanPath,2,null,null,null,'vfs.sessionKey');
        var count = 0;

        if(readNode == "-1")
        {
            alert("error");
            return -1;
        }

        else if(readNode.Data.length > 0 && readNode.Type == 1)
        {
            while(count < readNode.Data.length)
            {
                    currNode = readNode.Data[count];
                    benix.fsCopy(cleanPath+"/"+currNode.Name,destPath+"/"+currNode.Name,flags);
                    count++;             
            }
        }
    }      
      
    else if(benix.read(sourcePath,CHECKDIR,null,null,'vfs.sessionKey') && flags=="0r")
    {
        benix.write(destPath,CREATEDIR,1,null,null,'vfs.sessionKey');
             
        readNode =  benix.read(sourcePath,2,null,null,null,'vfs.sessionKey');
        var count = 0;

        if(readNode == "-1")
        {
            alert("error2");
            return -1;
        }

        else if(readNode.Data.length > 0 && readNode.Type == 1)
        {
            while(count < readNode.Data.length)
            {
                    currNode = readNode.Data[count];
                    benix.fsCopy(sourcePath+"/"+currNode.Name,destPath+"/"+currNode.Name,flags);
                    count++;             
            }
        }
    }
    else if(vfs.read(sourcePath,CHECKDIR,null,null,null) && flags!="-r")
    {
       return -1 
    }
    else
    {
        buffer = vfs.read(sourcePath,GETFILEDATA,null,null,null);
        return(vfs.write(destPath,CREATEDATAFILE,buffer,null,null,null) );
    };

    return -1;
};

benix.fsWalk = function(startNode,path)
{
    if(path.length==1 && path.charAt(0) == '/')
    {
        return startNode;
    }

    if(path.charAt(0) != '/')
    {
        return -1;
    }
    
    var nodeArray = path.split("/");
   
    aNode = startNode.Data[0];
        
    depth = 1;
    
    while(aNode && aNode.Name != nodeArray[nodeArray.length-1] && depth <= nodeArray.length)
    {
       while(aNode.Name != nodeArray[depth] && depth <= nodeArray.length )
        {      
                if(aNode.next != 0)
                {
                    aNode = aNode.next;
                }
                else
                {
                    return -1;
                }
        };    
        if(aNode.Name != nodeArray[nodeArray.length-1] && aNode.Type != 5 && aNode.Type != 6)
        {
            aNode=aNode.Data[0];
            depth++;
        }   
        
        if(aNode && aNode.Name == nodeArray[nodeArray.length-1] && depth < nodeArray.length-1)
        {
            znode = 0;
            while(aNode.Data[znode].Name != nodeArray[depth+1] && depth <= nodeArray.length )
            {   
                if(aNode.Data[znode].next!=0)
                    znode++;
                else
                    return -1;
            }; 
            if(aNode.Data[znode].Name == nodeArray[depth+1])
            {
                depth++;
                aNode=aNode.Data[znode];
            }
            else
                return -1;
        } 

        if(aNode && aNode.Type == 5 )
        {
            if(aNode.Name == nodeArray[depth])
                return(aNode);
            else
                return -1;
        }; 
        if(aNode && aNode.Type == 4 )
        {
            if(aNode.Name == nodeArray[depth])
                return(aNode);
            else
                return -1;
        }; 
        if(aNode && aNode.Type == 6 )
        {
            if(aNode.Name == nodeArray[depth])
                return(aNode);
            else
                return -1;
        };
     
        if(!aNode)
            return -1;
    };
        return aNode;
};

benix.fsBuildMountPath = function(mNode,mountPath)
{
     var name = mountPath.split("/");
     var path = '';
     var i = 1;
     
     while(i < name.length-1)
     {
        path += '/' + name[i];
        i++;
     }
       
    return path;
};

benix.parsePath = function(mNode,loadPath)
{
    var mPath = '';
    var counter = 0;
    
    var pathArray = loadPath.split('/');
    
    while(pathArray[counter] != mNode.Name && counter < pathArray.length)
    {
        counter++;
    }
    
    //skip the mount point's name
    counter++;
    
    while( counter < pathArray.length)
    {
        mPath = mPath + "/" + pathArray[counter];
        counter++;
    }
    if(mPath)   
        return mPath;
    else
        return('/');
};
/*
(function(){
    BObject = function(){};
    BObject.create = function(constructor)
    {
        var construct = this;
        c = function(){
                this._super = construct;
                var pubs = constructor.apply(this,args), self = this;
                for (key in pubs) (function(fn,sfn)
                {
                    self[key] = typeof fn != "function" || typeof sfn != "function" ? fn :function()
                    {
                        this._super = sfn;return fn.apply(this,args);
                    }
                };
            }
            c.prototype = new this;
            c.protoctype.constructor = c;
            c.extend = this.extend || this.create;
        };
    };
})();
*/

(function(){
  BObject = function(){};
  BObject.create = function(constructor) {
    var k = this;
    c = function() {
      this._super = k;
      var pubs = constructor.apply(this, arguments), self = this;
      for (key in pubs) (function(fn, sfn) {
        self[key] = typeof fn != "function" || typeof sfn != "function" ? fn :
          function() { this._super = sfn; return fn.apply(this, arguments); };
      })(pubs[key], self[key]);
    }; 
    c.prototype = new this;
    c.prototype.constructor = c;
    c.extend = this.extend || this.create;
    return c;
  };
})();